/*  
    Copyright 2010 Mike Eheler <mike.eheler@gmail.com>

    This file is part of Four Falling Blocks Puzzle Game.

    Four Falling Blocks Puzzle Game is free software: you can
	redistribute it and/or modify it under the terms of the GNU General
	Public License as published by the Free Software Foundation, either
	version 3 of the License, or (at your option) any later version.

    Four Falling Blocks Puzzle Game is distributed in the hope that it
	will be useful, but WITHOUT ANY WARRANTY; without even the implied
	warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Four Falling Blocks Puzzle Game.
	
	If not, see <http://www.gnu.org/licenses/>.
*/

#include "fbpiecepreview.moh"
#include "../../debug_console.h"

FBPiecePreview::FBPiecePreview( QWidget * parent )
  : QGLWidget( parent ),
	mPiece( 0 )
{
}

void FBPiecePreview::initializeGL()
{
	glClearDepth( 1.0 );
	glPolygonOffset( 1.0f, 1.0f );

	glEnable( GL_DEPTH_TEST );
	glEnable( GL_CULL_FACE );
}

void FBPiecePreview::resizeGL( int width, int height )
{
	double aspect = static_cast<double>(width) / height;

	glViewport( 0, 0, width, height );

	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();
	gluPerspective( 20.0, aspect, 1.0, 20.0 );

	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();

	gluLookAt( -3.0, 3.0, 7.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
}

static void cube()
{
	static GLuint id = 0;

	if( !glIsList(id) )
	{
		id = glGenLists( 1 );
		glNewList( id, GL_COMPILE_AND_EXECUTE );

		glBegin( GL_QUADS );
			// bottom
			glVertex3i( 0, 0, 0 );
			glVertex3i( 1, 0, 0 );
			glVertex3i( 1, 0, 1 );
			glVertex3i( 0, 0, 1 );

			// top
			glVertex3i( 0, 1, 0 );
			glVertex3i( 0, 1, 1 );
			glVertex3i( 1, 1, 1 );
			glVertex3i( 1, 1, 0 );

			// back
			glVertex3i( 0, 0, 0 );
			glVertex3i( 0, 1, 0 );
			glVertex3i( 1, 1, 0 );
			glVertex3i( 1, 0, 0 );

			// right
			glVertex3i( 1, 0, 0 );
			glVertex3i( 1, 1, 0 );
			glVertex3i( 1, 1, 1 );
			glVertex3i( 1, 0, 1 );

			// front
			glVertex3i( 1, 0, 1 );
			glVertex3i( 1, 1, 1 );
			glVertex3i( 0, 1, 1 );
			glVertex3i( 0, 0, 1 );

			// left
			glVertex3i( 0, 0, 1 );
			glVertex3i( 0, 1, 1 );
			glVertex3i( 0, 1, 0 );
			glVertex3i( 0, 0, 0 );
		glEnd();

		glEndList();
	}
	else
		glCallList( id );
}

static void drawPiece( int piece, bool wire = false )
{
	switch( piece )
	{
	case 0: // I
		if( !wire ) glColor3f( 0.0f, 1.0f, 1.0f );
		glTranslatef( -2.0f, -0.5f, -0.5f );
		for( int i = 0; i < 4; i++ )
		{
			cube();
			glTranslatef( 1.0f, 0.0f, 0.0f );
		}
		break;

	case 1: // J
		if( !wire ) glColor3f( 0.0f, 0.0f, 1.0f );
		glTranslatef( -1.5f, 0.0f, -0.5f );

		cube();
		glTranslatef( 0.0f, -1.0f, 0.0f ); cube();
		glTranslatef( 1.0f, 0.0f, 0.0f ); cube();
		glTranslatef( 1.0f, 0.0f, 0.0f ); cube();
		break;

	case 2: // L
		if( !wire ) glColor3f( 1.0f, 2.0f/3.0f, 0.0f );
		glTranslatef( -1.5f, -1.0f, -0.5f );

		cube();
		glTranslatef( 1.0f, 0.0f, 0.0f ); cube();
		glTranslatef( 1.0f, 0.0f, 0.0f ); cube();
		glTranslatef( 0.0f, 1.0f, 0.0f ); cube();
		break;

	case 3: // O
		if( !wire ) glColor3f( 1.0f, 1.0f, 0.0f );
		glTranslatef( -1.0f, -1.0f, -0.5f );
		
		cube();
		glTranslatef( 0.0f, 1.0f, 0.0f ); cube();
		glTranslatef( 1.0f, 0.0f, 0.0f ); cube();
		glTranslatef( 0.0f, -1.0f, 0.0f ); cube();
		break;

	case 4: // S
		if( !wire ) glColor3f( 0.0f, 1.0f, 0.0f );
		glTranslatef( -1.5f, -1.0f, -0.5f );

		cube();
		glTranslatef( 1.0f, 0.0f, 0.0f ); cube();
		glTranslatef( 0.0f, 1.0f, 0.0f ); cube();
		glTranslatef( 1.0f, 0.0f, 0.0f ); cube();
		break;

	case 5: // T
		if( !wire ) glColor3f( 2.0f / 3.0f, 0.0f, 1.0f );
		glTranslatef( -1.5f, -1.0f, -0.5f );

		cube();
		glTranslatef( 1.0f, 0.0f, 0.0f ); cube();
		glTranslatef( 0.0f, 1.0f, 0.0f ); cube();
		glTranslatef( 1.0f, -1.0f, 0.0f ); cube();
		break;

	case 6: // Z
		if( !wire ) glColor3f( 1.0f, 0.0f, 0.0f );
		glTranslatef( -1.5f, 0.0f, -0.5f );

		cube();
		glTranslatef( 1.0f, 0.0f, 0.0f ); cube();
		glTranslatef( 0.0f, -1.0f, 0.0f ); cube();
		glTranslatef( 1.0f, 0.0f, 0.0f ); cube();
		break;
	};
}

void FBPiecePreview::paintGL()
{
	#ifdef DEBUG
	GLenum err = glGetError();
	if( err != GL_NO_ERROR )
	{
		DebugConsole::error( reinterpret_cast<char const *>(gluErrorString(err)) );
	}
	#endif

	QColor clr( palette().color( backgroundRole() ) );
	glClearColor( clr.redF(), clr.greenF(), clr.blueF(), 1.0f );

	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	glPushMatrix();
		glPushMatrix();
			glEnable( GL_POLYGON_OFFSET_FILL );
			glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
			drawPiece( piece() );
		glPopMatrix();

		glPushMatrix();
			glDisable( GL_POLYGON_OFFSET_FILL );
			glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
			glColor4f( 0.0f, 0.0f, 0.0f, 1.0f );
			drawPiece( piece(), true );
		glPopMatrix();
	glPopMatrix();
}
